
/* Include -------------------------------------------------------------------*/
#include "sf_i2c.h"
#include "sf_i2c_demo.h"

#include "delay.h"

/* Private function ----------------------------------------------------------*/
static void i2c0_sda_pin_low(void);
static void i2c0_sda_pin_high(void);
static void i2c0_scl_pin_low(void);
static void i2c0_scl_pin_high(void);
static uint8_t i2c0_sda_pin_read(void);
static void i2c0_sda_pin_dir_input(void);
static void i2c0_sda_pin_dir_output(void);

static unsigned char s_I2CADR;

/**
 * @brief  i2c software delay function, used to control the i2c bus speed
 * @param  dev : Pointer to iic structure
 * @return none
 */
static void i2c_delay(const uint32_t us)
{
    delay_1us(us);
}



/* Private variables ---------------------------------------------------------*/
// 定义i2c驱动对象
static struct sf_i2c_dev i2c0_dev = {
    /*.name               = */ "i2c0",
    /*.addr               = */ 0x29,
    /*.speed              = */ 2, /*! speed:105Hz */
    /*.delay_us           = */ i2c_delay,
    /*.ops.sda_low        = */ i2c0_sda_pin_low,
    /*.ops.sda_high       = */ i2c0_sda_pin_high,
    /*.ops.scl_low        = */ i2c0_scl_pin_low,
    /*.ops.scl_high       = */ i2c0_scl_pin_high,
    /*.ops.sda_read_level = */ i2c0_sda_pin_read,
    /*.ops.sda_set_input  = */ i2c0_sda_pin_dir_input,
    /*.ops.sda_set_output = */ i2c0_sda_pin_dir_output,
};

// SCL PA8
// SDA PC9

#define SW_MAIN_SCL_PIN                   GPIO_PIN_8
#define SW_MAIN_SCL_PORT                  GPIOA
#define SW_MAIN_SCL_CLK                   RCU_GPIOA

#define SW_MAIN_SDA_PORT                  GPIOC
#define SW_MAIN_SDA_PIN                   GPIO_PIN_9
#define SW_MAIN_SDA_CLK                   RCU_GPIOC

/*! Set i2c sda pin low level */
static void i2c0_sda_pin_low(void)
{
    gpio_bit_reset(SW_MAIN_SDA_PORT, SW_MAIN_SDA_PIN);
}

/*! Set i2c sda pin high level */
static void i2c0_sda_pin_high(void)
{
    gpio_bit_set(SW_MAIN_SDA_PORT, SW_MAIN_SDA_PIN);
}

/*! Set i2c scl pin low level */
static void i2c0_scl_pin_low(void)
{
    gpio_bit_reset(SW_MAIN_SCL_PORT, SW_MAIN_SCL_PIN);
}

/*! Set i2c scl pin high level */
static void i2c0_scl_pin_high(void)
{
    gpio_bit_set(SW_MAIN_SCL_PORT, SW_MAIN_SCL_PIN);
}

/*! Read i2c sda pin level */
static uint8_t i2c0_sda_pin_read(void)
{
    return gpio_input_bit_get(SW_MAIN_SDA_PORT, SW_MAIN_SDA_PIN);
}

/*! Switch i2c sda pin dir input */
static void i2c0_sda_pin_dir_input(void)
{
    gpio_mode_set(SW_MAIN_SDA_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SW_MAIN_SDA_PIN);
}

/*! Switch i2c sda pin dir output */
static void i2c0_sda_pin_dir_output(void)
{
    gpio_mode_set(SW_MAIN_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SW_MAIN_SDA_PIN);
}

/**
 * @brief  Initialization i2c0 physical interface
 * @param  none
 * @return none
 */
static void i2c0_port_init(void)
{
    /* enable the GPIO, Interrupt clock*/
    rcu_periph_clock_enable(SW_MAIN_SDA_CLK);
    rcu_periph_clock_enable(SW_MAIN_SCL_CLK);
    rcu_periph_clock_enable(RCU_SYSCFG);

    gpio_mode_set(SW_MAIN_SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SW_MAIN_SCL_PIN);
    gpio_output_options_set(SW_MAIN_SCL_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SW_MAIN_SCL_PIN);
    
    gpio_mode_set(SW_MAIN_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,           SW_MAIN_SDA_PIN);
    gpio_output_options_set(SW_MAIN_SDA_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SW_MAIN_SDA_PIN);
}

/**
 * @brief  Initialization board i2c0 interface
 * @param  none
 * @return none
 */
void sf_i2c_demo_init(void)
{
    /*! i2c physical layer initialization */
    i2c0_port_init();

    /*! i2c software layer initialization */
    sf_i2c_init(&i2c0_dev);
    s_I2CADR = i2c0_dev.dev_addr7;
}

unsigned char I2C_Read_Byte(unsigned char RegAddr)
{
    unsigned char read_val[1];
	struct sf_i2c_msg msgs[2];
	
	// 写目标寄存器地址
	msgs[0].addr  = s_I2CADR;
    msgs[0].flags = SF_I2C_FLAG_WR;
    msgs[0].buf   = &RegAddr;
    msgs[0].len   = 1;
    
    // 从目标寄存器地址连续读len个数据
    msgs[1].addr  = s_I2CADR;
    msgs[1].flags = SF_I2C_FLAG_RD;
    msgs[1].buf   = read_val;
    msgs[1].len   = 1;
    sf_i2c_transfer(&i2c0_dev, msgs, 2);
    return read_val[0];
}

void I2C_Write_Byte(unsigned char RegAddr,unsigned char data)
{
    unsigned char test_data[1];
	struct sf_i2c_msg msgs[2];

	test_data[0] = data;
	// 写目标寄存器地址
	msgs[0].addr  = s_I2CADR;
    msgs[0].flags = SF_I2C_FLAG_WR;
    msgs[0].buf   = &RegAddr;
    msgs[0].len   = 1;
    
    // 向目标寄存器地址 写数据
    msgs[1].addr  = s_I2CADR;
    msgs[1].flags = SF_I2C_FLAG_WR | SF_I2C_FLAG_NO_START;
    msgs[1].buf   = test_data;
    msgs[1].len   = 1;
    sf_i2c_transfer(&i2c0_dev, msgs, 2);
}

void I2C_Write_ByteN(unsigned char RegAddr, unsigned char *pData, unsigned short length)
{
	unsigned short i = 0;
	for(i = 0; i < length; i++)
	{
		I2C_Write_Byte(RegAddr + i, pData[i]);
	}
}

void I2C_Read_ByteN(unsigned char RegAddr, unsigned char *pData, unsigned short length)
{
	unsigned short i = 0;
	for(i = 0; i < length; i++)
	{
		pData[i] = I2C_Read_Byte(RegAddr + i);
	}
}
